package com.atguigu.gmall.order.controller;

import com.atguigu.gmall.cart.client.CartFeignClient;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.common.util.AuthContextHolder;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.model.user.UserAddress;
import com.atguigu.gmall.order.service.OrderService;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.atguigu.gmall.user.client.UserFeignClient;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang.StringUtils;
import org.apache.tomcat.util.threads.ThreadPoolExecutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@RestController
@RequestMapping("api/order")
public class OrderApiController {

    @Autowired
    private UserFeignClient userFeignClient;
    @Autowired
    private CartFeignClient cartFeignClient;
    @Autowired
    private OrderService orderService;
    @Autowired
    private ProductFeignClient productFeignClient;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    //订单结算页面 远程调用url
    @GetMapping("auth/trade")
    public Result authTrade(HttpServletRequest request){
        HashMap<String, Object> hashMap = new HashMap<>();
        //获取用户Id
        String userId = AuthContextHolder.getUserId(request);
        //获取收货地址列表
        List<UserAddress> userAddressList = userFeignClient.findUserAddressListByUserId(userId);
        //获取订单明细集合 赋值给detailArrayList
        List<CartInfo> cartCheckedList = cartFeignClient.getCartCheckedList(userId);
        AtomicInteger totalNum = new AtomicInteger();//CAS 保持原子性 只有多线程会
        List<OrderDetail> detailArrayList = cartCheckedList.stream().map(cartInfo -> {
            //声明一个订单明细
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setSkuId(cartInfo.getSkuId());
            orderDetail.setSkuName(cartInfo.getSkuName());
            orderDetail.setSkuNum(cartInfo.getSkuNum());
            orderDetail.setImgUrl(cartInfo.getImgUrl());
            orderDetail.setOrderPrice(cartInfo.getSkuPrice());
            //计算商品总件数
            totalNum.addAndGet(cartInfo.getSkuNum());//保持原子性
            return orderDetail;
        }).collect(Collectors.toList());

        //声明一个订单
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setOrderDetailList(detailArrayList);
        orderInfo.sumTotalAmount();

        hashMap.put("userAddressList",userAddressList);//用户收货地址集合
        hashMap.put("detailArrayList",detailArrayList);//订单明细集合
        hashMap.put("totalNum",totalNum);//商品总件数
        hashMap.put("totalAmount",orderInfo.getTotalAmount());//商品总价格
        hashMap.put("tradeNo",this.orderService.getTradeNo(userId));//流水号
        return Result.ok(hashMap);
    }

    //提交订单
    @PostMapping("auth/submitOrder")
    public Result submitOrder(@RequestBody OrderInfo orderInfo,HttpServletRequest request){
        String userId = AuthContextHolder.getUserId(request);
        orderInfo.setUserId(Long.parseLong(userId));
        //获取页面传递的流水号
        String tradeNo = request.getParameter("tradeNo");
        //调用比较方法
        Boolean result = this.orderService.checkTradeNo(tradeNo, userId);
        if (!result){
            return Result.fail().message("不能重复无刷新回退订单");
        }
        //删除流水号
        this.orderService.delTradeNo(userId);
        //校验库存
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        //循环
//        orderDetailList.forEach(orderDetail -> {
//            Long skuId = orderDetail.getSkuId();
//            Integer skuNum = orderDetail.getSkuNum();
//            //调用校验库存系统接口
//            Boolean exist = this.orderService.checkStock(skuId,skuNum);
//            if (!exist){
//                return Result.fail().message(orderDetail.getSkuId()+"库存不足");
//            }
//        });
        //声明一个多线程集合
        ArrayList<CompletableFuture> completableFutureArrayList = new ArrayList<>();
        //声明一个String类型集合来存储 信息提示
        ArrayList<String> errorList = new ArrayList<>();
        for (OrderDetail orderDetail : orderDetailList) {
            Long skuId = orderDetail.getSkuId();
            Integer skuNum = orderDetail.getSkuNum();
            CompletableFuture<Void> stockCompletableFuture = CompletableFuture.runAsync(() -> {
                //调用校验库存系统接口
                Boolean exist = this.orderService.checkStock(skuId, skuNum);
                if (!exist) {
                    //return Result.fail().message(orderDetail.getSkuId()+"库存不足");
                    errorList.add(orderDetail.getSkuId() + "库存不足");
                }
            },threadPoolExecutor);
            CompletableFuture<Void> priceCompletableFuture = CompletableFuture.runAsync(() -> {
                //获取订单价格
                BigDecimal orderPrice = orderDetail.getOrderPrice();
                //获取实时价格
                BigDecimal skuPrice = this.productFeignClient.getSkuPrice(skuId);
                //校验商品价格
                //什么时候涨价 什么时候降价
                if (orderPrice.compareTo(skuPrice) != 0) {
                    String msg = orderPrice.compareTo(skuPrice) > 0 ? "降价" : "涨价";
                    //变动了多少 变动的价格
                    BigDecimal price = orderPrice.subtract(skuPrice).abs();
                    //自动更新购物车的价格
                    String cartKey = RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
                    CartInfo cartInfo = (CartInfo) this.redisTemplate.opsForHash().get(cartKey, skuId.toString());
                    cartInfo.setSkuPrice(skuPrice);
                    this.redisTemplate.opsForHash().put(cartKey, skuId.toString(), cartInfo);
                    //return Result.fail().message(orderDetail.getSkuId()+"价格"+msg+price+"元");
                    errorList.add(orderDetail.getSkuId() + "价格" + msg + price + "元");
                }
            },threadPoolExecutor);
            //添加到集合
            completableFutureArrayList.add(stockCompletableFuture);
            completableFutureArrayList.add(priceCompletableFuture);
        }
        //多任务组合
        CompletableFuture.allOf(completableFutureArrayList
                .toArray(new CompletableFuture[completableFutureArrayList.size()]))
                .join();
        if (errorList.size()>0){
            //将集合中的数据使用  , 进行拼接成字符串
            return Result.fail().message(StringUtils.join(errorList,","));
        }
        Long orderId = this.orderService.saveOrderInfo(orderInfo);
        //返回订单Id
        return Result.ok(orderId);
    }

    //查看我的订单
    @GetMapping("auth/{page}/{limit}")
    public Result getMyOrderList(@PathVariable Long page,
                                 @PathVariable Long limit,
                                 HttpServletRequest request){
        String userId = AuthContextHolder.getUserId(request);
        Page<OrderInfo> orderInfoPage = new Page<>(page,limit);
        String orderStatus = request.getParameter("orderStatus");
        //调用服务层方法
        IPage<OrderInfo> orderInfoIPage = this.orderService.getMyOrderList(orderInfoPage,userId,orderStatus);
        return Result.ok(orderInfoIPage);
    }
    @GetMapping("inner/getOrderInfo/{orderId}")
    public OrderInfo getOrderInfo(@PathVariable Long orderId){
        OrderInfo orderInfo = this.orderService.getOrderInfo(orderId);
        return orderInfo;
    }

    //http://localhost:8204/api/order/orderSplit
    //拆单
    @PostMapping("orderSplit")
    public List<Map> orderSplit(HttpServletRequest request){
        //获取传递的参数  订单id
        String orderId = request.getParameter("orderId");
        //仓库id与skuId的对应关系
        String wareSkuMap = request.getParameter("wareSkuMap");
        //获取子订单的集合
        List<OrderInfo> orderInfoList = this.orderService.orderSplit(orderId,wareSkuMap);
        //循环遍历
        List<Map> mapList = orderInfoList.stream().map(orderInfo -> {
            Map map = this.orderService.wareJson(orderInfo);
            return map;
        }).collect(Collectors.toList());
        return mapList;
    }

    @PostMapping("inner/seckill/submitOrder")
    public Long saveSeckillOrder(@RequestBody OrderInfo orderInfo){
        Long orderId = this.orderService.saveOrderInfo(orderInfo);
        return orderId;
    }

}
